package com.wyd.filter.exception;

import com.wyd.common.Result;
import com.wyd.exception.ErrorCode;
import com.wyd.exception.ServerException;
import com.wyd.exception.ServiceException;
import com.wyd.utils.WebFrameworkUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.core.annotation.Order;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;


/**
 * Gateway 的全局异常处理器，将 Exception 翻译成 CommonResult + 对应的异常编号
 *
 * 在功能上，和 yudao-spring-boot-starter-web 的 GlobalExceptionHandler 类是一致的
 *
 * @author 芋道源码
 */
@Component
@Order(-100) // 保证优先级高于默认的 Spring Cloud Gateway 的 ErrorWebExceptionHandler 实现
@Slf4j
public class GlobalExceptionHandler implements ErrorWebExceptionHandler {

    ErrorCode INTERNAL_SERVER_ERROR = new ErrorCode(500, "系统异常");

    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        // 已经 commit，则直接返回异常
        ServerHttpResponse response = exchange.getResponse();
        if (response.isCommitted()) {
            return Mono.error(ex);
        }

        // 转换成 CommonResult
        Result result;
        if (ex instanceof ResponseStatusException) {
            result = responseStatusExceptionHandler(exchange, (ResponseStatusException) ex);
        } else {
            result = defaultExceptionHandler(exchange, ex);
        }

        // 返回给前端
        return WebFrameworkUtils.writeJSON(exchange, result);
    }

    /**
     * 处理 Spring Cloud Gateway 默认抛出的 ResponseStatusException 异常
     */
    private Result responseStatusExceptionHandler(ServerWebExchange exchange, ResponseStatusException ex) {
        ServerHttpRequest request = exchange.getRequest();
        log.error("[responseStatusExceptionHandler][uri({}/{}) 发生异常]", request.getURI(), request.getMethod(), ex);
        return Result.error(ex.getRawStatusCode(), ex.getReason());
    }

    /**
     * 处理系统异常，兜底处理所有的一切
     */
    @ExceptionHandler(value = Exception.class)
    public Result defaultExceptionHandler(ServerWebExchange exchange, Throwable ex) {
        ServerHttpRequest request = exchange.getRequest();

        if(ex instanceof ServerException){
            log.error("[ServerException][uri({}/{}) 发生异常]", request.getURI(), request.getMethod(), ex);
            ServerException err = (ServerException)ex;
            return Result.error(err.getCode(), err.getMessage());

        }else if(ex instanceof ServiceException){
            log.error("[ServiceException][uri({}/{}) 发生异常]", request.getURI(), request.getMethod(), ex);
            ServiceException err = (ServiceException)ex;
            return Result.error(err.getCode(), err.getMessage());

        }else{
            log.error("[defaultExceptionHandler][uri({}/{}) 发生异常]", request.getURI(), request.getMethod(), ex);
            return Result.error(INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg());
        }
    }

}
